package experiment;

import java.awt.Point;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import java.io.File;
import javax.media.opengl.GLCanvas;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

import ui.timeline.OneThumbTimeLineSlider;
import ui.timeline.ThreeThumbTimeLineSlider;
import ui.timeline.TwoThumbTimeLineSlider;


public class EventLogger implements MouseListener, KeyListener, MouseWheelListener, MouseMotionListener, ChangeListener {

	
	public Experiment experiment;
	public File file;
	

	public long lowerRangeTimeSlindingStartTime = 0;
	public long lowerRangeTimeSlindingEndTime = 0;
	
	private boolean upperThumbIsDragging = false;
	private boolean lowerThumbIsDragging = false;
	private boolean currentThumbIsDragging = false;
	private long timeSliderStartTime;

	private int xTimeDraggingValue = 0;
	private int yTimeDraggingValue = 0;
	
	private Point position;
	private boolean isWheelBeingUsed;
	private String wheelDirection = "";
	private double wheelValue = 0;
	private long wheelStartTime = 0;
	private long wheelEndTime = 0;
	private int xCameraPan;
	private int yCameraPan;
	private long cameraPanStartTime;
	
	private ExperimentLogger experimentLogger;
	
	public EventLogger(ExperimentManager experimentManager)
	{
		this.experiment = experimentManager.getExperiment();
		this.experimentLogger = experimentManager.getExperimentLogger();
	}
	
	@Override
	public void mouseWheelMoved(MouseWheelEvent event) 
	{
		// TODO Auto-generated method stub
		this.experimentLogger.addFullLog(System.currentTimeMillis() + ";" + event + "\n");
		if(event.getSource().getClass() == GLCanvas.class)
		{
			
			if( (event.getPreciseWheelRotation() * this.wheelValue) < 0)
			{
				this.wheelComputing();
			}
			
			if(event.getPreciseWheelRotation() < 0)
			{
				wheelDirection = "zoomDown;";
			}
			else if ( event.getPreciseWheelRotation() > 0 )
			{
				wheelDirection = "zoomUp;";
			}
			
			this.wheelValue += event.getPreciseWheelRotation();
			if(this.wheelStartTime ==0)
			{
				this.wheelStartTime = System.currentTimeMillis();
			}
			
			this.wheelEndTime = System.currentTimeMillis();
			this.isWheelBeingUsed = true;
		}
	}
	
	public void wheelComputing()
	{
		if(this.isWheelBeingUsed)
		{
			long elapsedTime = this.wheelEndTime - this.wheelStartTime;
			String source = "RenderEngine;";
			ExperimentAction action = new ExperimentAction(source, wheelDirection, this.wheelStartTime, this.wheelEndTime, elapsedTime, 0, this.wheelValue);
			this.experimentLogger.addExperimentAction(action);
			this.wheelDirection = "";
			this.wheelStartTime = 0;
			this.wheelValue = 0;
			this.isWheelBeingUsed = false;
		}
	}

	@Override
	public void keyPressed(KeyEvent event) {
		// TODO Auto-generated method stub
		this.experimentLogger.addFullLog(System.currentTimeMillis() + ";" + event + "\n");
	}

	@Override
	public void keyReleased(KeyEvent event) {
		// TODO Auto-generated method stub
		this.experimentLogger.addFullLog(System.currentTimeMillis() + ";" + event + "\n");
	}

	@Override
	public void keyTyped(KeyEvent event) {
		// TODO Auto-generated method stub
		this.experimentLogger.addFullLog(System.currentTimeMillis() + ";" + event + "\n");
	}

	@Override
	public void mouseClicked(MouseEvent event) {
		// TODO Auto-generated method stub
		this.experimentLogger.addFullLog(System.currentTimeMillis() + ";" + event + "\n");
	}

	@Override
	public void mouseEntered(MouseEvent event) {
		// TODO Auto-generated method stub
		this.experimentLogger.addFullLog(System.currentTimeMillis() + ";" + event + "\n");
	}

	@Override
	public void mouseExited(MouseEvent event) {
		// TODO Auto-generated method stub

		this.experimentLogger.addFullLog(System.currentTimeMillis() + ";" + event + "\n");
	}

	@Override
	public void mousePressed(MouseEvent event) {
		// TODO Auto-generated method stub

		this.experimentLogger.addFullLog(System.currentTimeMillis() + ";" + event + "\n");
		if( event.getSource().getClass() == GLCanvas.class && event.getButton() == MouseEvent.BUTTON3)
		{
			this.xCameraPan = 0;
			this.yCameraPan = 0;
			
			this.cameraPanStartTime = System.currentTimeMillis();
		}
	}

	@Override
	public void mouseReleased(MouseEvent event) {
		// TODO Auto-generated method stub
		if( event.getSource().getClass() == GLCanvas.class && event.getButton() == MouseEvent.BUTTON3)
		{
			long endTime = System.currentTimeMillis();
			long elapsedTime = endTime - this.cameraPanStartTime;
			
			ExperimentAction action = new ExperimentAction("RenderEngine", "CameraPan", this.cameraPanStartTime, endTime, elapsedTime, this.xCameraPan, this.yCameraPan);
			this.experimentLogger.addExperimentAction(action);
			
			this.position = null;
			this.xCameraPan = 0;
			this.yCameraPan = 0;
		}
	}

	@Override
	public void mouseDragged(MouseEvent event) {
		// TODO Auto-generated method stub
		this.experimentLogger.addFullLog(System.currentTimeMillis() + ";" + event + "\n");
		if(event.getSource().getClass() == ThreeThumbTimeLineSlider.class)
		{
			Point newPosition = event.getPoint();
			if(this.position != null)
			{
				this.xTimeDraggingValue += Math.abs(newPosition.x - this.position.x);
				this.yTimeDraggingValue += Math.abs(newPosition.y - this.position.y);
			}
			this.position = event.getPoint();
		}
		else if( event.getSource().getClass() == GLCanvas.class && event.getModifiersEx() == MouseEvent.BUTTON3_DOWN_MASK)
		{
			Point newPosition = event.getPoint();
			if(this.position != null)
			{
				this.xCameraPan += Math.abs(newPosition.x - this.position.x);
				this.yCameraPan += Math.abs(newPosition.y - this.position.y);
			}
			this.position = event.getPoint();
		}
	}

	@Override
	public void mouseMoved(MouseEvent event) {
		// TODO Auto-generated method stub

		this.experimentLogger.addFullLog(System.currentTimeMillis() + ";" + event + "\n");
		this.wheelComputing();
	}

	@Override
	public void stateChanged(ChangeEvent event) {

		this.experimentLogger.addFullLog(System.currentTimeMillis() + ";" + event + "\n");
		if( event.getSource().getClass() == TwoThumbTimeLineSlider.class)
		{
			TwoThumbTimeLineSlider slider = ((TwoThumbTimeLineSlider) event.getSource());
			if(slider.upperIsDragging())
			{
				this.upperThumbIsDragging = true;
				this.timeSliderStartTime = System.currentTimeMillis();
			}
			else if(slider.isDragging())
			{
				this.currentThumbIsDragging = true;
				this.timeSliderStartTime = System.currentTimeMillis();
			}
			else
			{

				String thumb = "";
				if(this.upperThumbIsDragging)
				{
					thumb = "upperThumb;";
					this.upperThumbIsDragging = false;
				}
				else if(this.lowerThumbIsDragging)
				{
					thumb = "lowerThumb;";
					this.lowerThumbIsDragging = false;
				}
				else if(this.currentThumbIsDragging)
				{
					thumb = "currentThumb;";
					this.currentThumbIsDragging = false;
				}
				long endTime =  System.currentTimeMillis();
				long elapsedTime = endTime - this.timeSliderStartTime;		

				ExperimentAction action = new ExperimentAction("TimeLine", thumb, this.timeSliderStartTime, endTime, elapsedTime, this.xTimeDraggingValue, this.yTimeDraggingValue);
				this.experimentLogger.addExperimentAction(action);
					
				this.position = null;
				this.xTimeDraggingValue = 0;
				this.yTimeDraggingValue = 0;
			}	
		}
		else if( event.getSource().getClass() == OneThumbTimeLineSlider.class)
		{
			OneThumbTimeLineSlider slider = ((OneThumbTimeLineSlider) event.getSource());
			if(slider.isDragging())
			{
				this.currentThumbIsDragging = true;
				this.timeSliderStartTime = System.currentTimeMillis();
			}
			else
			{
				String thumb = "";
				if(this.upperThumbIsDragging)
				{
					thumb = "upperThumb;";
					this.upperThumbIsDragging = false;
				}
				else if(this.lowerThumbIsDragging)
				{
					thumb = "lowerThumb;";
					this.lowerThumbIsDragging = false;
				}
				else if(this.currentThumbIsDragging)
				{
					thumb = "currentThumb;";
					this.currentThumbIsDragging = false;
				}
				long endTime =  System.currentTimeMillis();
				long elapsedTime = endTime - this.timeSliderStartTime;		

				ExperimentAction action = new ExperimentAction("TimeLine", thumb, this.timeSliderStartTime, endTime, elapsedTime, this.xTimeDraggingValue, this.yTimeDraggingValue);
				this.experimentLogger.addExperimentAction(action);
					
				this.position = null;
				this.xTimeDraggingValue = 0;
				this.yTimeDraggingValue = 0;
			}	
		}
	}
}
